
#pragma once
#include "Skeleton.h"
#include "JointColor.h"
#include "ShaderObject.h"
#include "BmpImage.h"
#include "misc/nvmodel.h"

class Renderer
{
public:

	// public instance variables

	static Renderer * instance;
	static const int MAX_SKELETONS = 15;
	static const bool TEST_WITH_KINECT = true;

	// public methods

	void init(int argc, char **arg);
	void beginRenderingLoop(void);
	
	void setSkeleton(Skeleton * skeleton) {
		this->skeleton = skeleton;
	}

	Skeleton * getSkeleton() {
		return this->skeleton;
	}

	void setWidth(int width) {
		this->width = width;
	}

	int getWidth() {
		return this->width;
	}

	void setHeight(int height){
		this->height = height;
	}

	int getHeight() {
		return this->height;
	}


	bool getMovingForward() {
		return this->movingForward;
	}

	void setMovingForward(bool mf) {
		this->movingForward = mf;
	}

	bool getMovingBackward() {
		return this->movingBackward;
	}

	void setMovingBackward(bool mb) {
		this->movingBackward = mb;
	}

	bool getMovingRight() {
		return this->movingRight;
	}

	void setMovingRight(bool mr) {
		this->movingRight = mr;
	}

	bool getMovingLeft() {
		return this->movingLeft;
	}

	void setMovingLeft(bool ml) {
		this->movingLeft = ml;
	}




	static Renderer * getInstance() {
		if(!instance) {
			instance = new Renderer();
		}
		return instance;
	}

	void setIdleFunction(void (*idleFunction)(void));

	JointColor * getColors() {
		return this->colors;
	}

	void render(int i);
	void setBallCenter(float x, float y, float z);
	float getBallRadius();

private:

	// private constructors
	Renderer(void);
	~Renderer(void);

	// private instance variables
	Skeleton * skeleton;
	Skeleton * opponentSkeleton;
	ShaderObject * modelShader;
	ShaderObject * opponentShader;
	BmpImage * modelTexture;
	BmpImage * soccerFieldTexture;
	unsigned int modelTextureId;
	unsigned int modelJointTextureId;
	unsigned int soccerFieldTextureId;
	nv::Model * maleModel;
	unsigned int maleModelVbo;
	unsigned int maleModelIndexBuffer;

	

	int width;
	int height;

	bool movingForward;
	bool movingBackward;
	bool movingRight;
	bool movingLeft;

	float * headPos;
	float * neckPos;
	float * torsoPos;
	float * rShoulderPos;
	float * lShoulderPos;
	float * rElbowPos;
	float * lElbowPos;
	float * rHandPos;
	float * lHandPos;
	float * rHipPos;
	float * lHipPos;
	float * rKneePos;
	float * lKneePos;
	float * rFootPos;
	float * lFootPos;


	float * torsoOrigin;
	float * headOrigin;
	float * neckOrigin;
	float * rShoulderOrigin;
	float * lShoulderOrigin;
	float * rElbowOrigin;
	float * lElbowOrigin;
	float * rHandOrigin;
	float * lHandOrigin;
	float * rHipOrigin;
	float * rKneeOrigin;
	float * lHipOrigin;
	float * lKneeOrigin;
	float * rFootOrigin;
	float * lFootOrigin;


	float characterX;
	float characterZ;

	float opponentX;
	float opponentY;
	float opponentZ;
	float opponentXRot;

	float ballRadius;
	int ballSlices;
	int ballStacks;
	float ballCenterX;
	float ballCenterY;
	float ballCenterZ;
	bool kickedBall;

	float time;
	float acceleration;
	float velocity;

	float directionX;
	float directionY;
	float directionZ;

	float dx;
	float opponentDx;

	float vyf;
	float vyi;

	float multX;
	float multY;
	float multZ;

	int scoreFavor;
	int scoreAgainst;



	JointColor colors[MAX_SKELETONS];
	void (*idleFunction)(void);

	// private methods
	void initLights();
	void initColors();
	void initShaders();
	void initTextures();
	void initModels();

	void initController();
	void renderCharacter(int i);
	void renderField();
	void renderController();
	void checkMotion(int i);
	void renderBall();
	void checkIntersection(int i);
	float distance(float x1, float y1, float z1, float x2, float y2, float z2);
	void renderSphere(float centerX, float centerY, float centerZ, float radius);
	void updateBall();
	void renderGoal();
	void renderScore();
	void renderModel();
	void renderOpponent();
	void moveOpponent();
	
};




